/**
 * File CustomerControlAgentCB.java created by Pablo Díaz Fernández
 * on 06/04/2012 for the project supply-chain-simulator
 */
package org.lsk.pfc.scsim.model.behaviour;

import java.math.BigDecimal;
import java.util.List;

import jade.core.AID;
import jade.lang.acl.ACLMessage;

import org.apache.log4j.Logger;
import org.lsk.pfc.scsim.model.agent.ControlAgent;
import org.lsk.pfc.scsim.model.messages.InformationAgentMessageFactory;
import org.lsk.pfc.scsim.model.messages.MessageFactory;
import org.lsk.pfc.scsim.model.messages.NegotiationMessageFactory;

/**
 * Cyclic behaviour executed for the control agent of the customer multi-agent
 * system of the supply chain.
 * 
 * @author Pablo Díaz Fernández
 */
public final class CustomerControlAgentCB extends ControlAgentCB {

	/**
	 * Serial version ID.
	 */
	private static final long serialVersionUID = -6673095142793852577L;

	/**
	 * Creates the logger for the class.
	 * 
	 * @see org.lsk.pfc.scsim.model.behaviour.ControlAgentCB#createLogger()
	 */
	@Override
	protected void createLogger() {
		super.setLogger(Logger.getLogger(this.getClass()));
	}

	/**
	 * Performs the main operations of this behaviour. Queries
	 * {@link InformationAgent} for needs in this very tick and tries to provide
	 * them.
	 * 
	 * @param tick
	 *            current time tick.
	 * @see org.lsk.pfc.scsim.model.behaviour.ControlAgentCB#process(long)
	 */
	@Override
	protected void process(final long tick) {
		ControlAgent agent = (ControlAgent) this.myAgent;
		ACLMessage outIAMsg = MessageFactory.getInformationAgentMF()
		        .queryMessage(agent.getInformationAgentAID(), agent.getAID(),
		                tick, InformationAgentMessageFactory.NEEDS_MESSAGE);
		agent.send(outIAMsg);

		super.getLogger().debug(
		        "[" + agent.getName() + "] Needs req sent to ia \n" + outIAMsg);

		// Blocks behaviour execution until a response message is received.
		ACLMessage inIAMsg = agent
		        .blockingReceive(InformationAgentMessageFactory.RESPONSE_MSG_TEMPLATE);

		int amount = Integer.valueOf(inIAMsg.getContent());
		if (amount == 0) {
			super.getLogger().debug(
			        "[" + agent.getName()
			                + "] Info received: No needs for tick " + tick);
		} else {
			AID provider = findProvider(tick, agent, amount);
			ACLMessage outMsg = MessageFactory.getNegotiationMF()
			        .getRequestProductMSG(provider, agent.getAID(), tick,
			                amount);
			agent.send(outMsg);
			super.getLogger().debug(
			        "[" + agent.getName() + "] Info received: "
			                + outMsg.toString());
		}

	}

	/**
     * @param tick
     * @param agent
     * @param amount
     * @return
     */
    private AID findProvider(final long tick, ControlAgent agent, int amount) {
	    // Search for providers
	    List<AID> providers = agent.getProviders();
	    AID provider = null;
	    BigDecimal price = null;
	    Integer amountAvailable = null;
	    // For each provider negotiate price and amount
	    for (AID aid : providers) {
	    	ACLMessage outMsg = MessageFactory
	    	        .getNegotiationMF()
	    	        .getRequestProductMSG(aid, agent.getAID(), tick, amount);
	    	super.getLogger().debug(
	    	        "[" + agent.getName() + "] Info sent: "
	    	                + outMsg.toString());
	    	ACLMessage inMsg = agent.blockingReceive(
	    			NegotiationMessageFactory.NEG_RES_MSG_TEMPLATE);
	    	super.getLogger().debug(
	    	        "[" + agent.getName() + "] Info received: "
	    	                + inMsg.toString());
	    	
	    	//Calculate costs
	    	if (provider == null) {
	    		provider = aid;
	    		price = new BigDecimal(
	    		        inMsg.getUserDefinedParameter(
	    		        		NegotiationMessageFactory.PRICE));
	    		amountAvailable = Integer.valueOf(
	    				inMsg.getUserDefinedParameter(
	    						NegotiationMessageFactory.AMOUNT));
	    	} else {
	    		//
	    	}
	    }
	    return provider;
    }

}
